var EPSILON = 0.001;

function newLineFromPoints(lineGeom, beginning, distUnits) {
	var points = lineGeom.components;
	if (points.length < 2) return;
	
	var newLinePoints = new Array();
	
	for (var i = 0; i < points.length; i++)
		newLinePoints[i] = new OpenLayers.Geometry.Point(points[i].x, points[i].y);
	
	var lastIdx = points.length - 1;
	if (beginning)
		setPointDistance(newLinePoints[1], newLinePoints[0], distUnits);
	else
		setPointDistance(newLinePoints[lastIdx - 1], newLinePoints[lastIdx], distUnits);

	return new OpenLayers.Geometry.LineString(newLinePoints);
}
function newLineFromBearing(lineGeom, radAnle) {
	var points = lineGeom.components;
	if (points.length != 2) return;
	
	var newLinePoints = new Array();
	
	for (var i = 0; i < points.length; i++)
		newLinePoints[i] = new OpenLayers.Geometry.Point(points[i].x, points[i].y);
	
	setPointBearing(newLinePoints[0], newLinePoints[1], radAnle);
	
	return new OpenLayers.Geometry.LineString(newLinePoints);
}

function setPointBearing(p1, p2, radAnle) {
	var norm = distance(p1, p2);
	
	var dx = norm * Math.cos(radAnle);
	var dy = norm * Math.sin(radAnle);
	
	p2.x = p1.x + dx;
	p2.y = p1.y + dy;
}
function setPointDistance(p1, p2, distUnits) {
	var norm = distance(p1, p2);
	
	var dx = (p2.x - p1.x) / norm * distUnits; 
	var dy = (p2.y - p1.y) / norm * distUnits;
	
	p2.x = p1.x + dx;
	p2.y = p1.y + dy;
}

function distance(p1, p2) {
	return Math.sqrt((p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y));
}

function theta(p1, p2) {
	var theta = 0;
	
	var delta_x = Math.abs(p2.x - p1.x);
	if (delta_x > EPSILON) {
		length = distance(p1, p2);
		theta = Math.asin(delta_x / length);
	}

	return theta;
}

function cardinalDirection(p1, p2) {
	var diff_x = p2.x - p1.x;
	var diff_y = p2.y - p1.y;
	
	var thetaDegs = theta(p1, p2) * 180 / Math.PI;
	var result = "";
	if (Math.abs(thetaDegs - 90.0) > EPSILON) {
		result += "" + thetaDegs + "° ";
		if (diff_y > EPSILON)
			result += "N";
		else if (diff_y < -EPSILON)
			result += "S";

		if (diff_x > EPSILON)
			result += " E";
		else if (diff_x < -EPSILON)
			result += " W";
	}
	else if (Math.abs(thetaDegs - 0.0) < EPSILON) {
		result += "0.0° ";
		if (diff_y > 0)
			result += "N";
		else
			result += "S";
	}
	else {
		result += "90.0° ";
		if (diff_x > 0)
			result += "E";
		else
			result += "W";
	}
	
	return result;
}

function directionToRadAngle(direction) {
	direction = direction.trim();
	
	var angle = undefined;
	var numberPart = '';
	var orientationPart = '';
	
	var ch;
	for (var i = 0; i < direction.length; i++) {
		ch = direction[i];
		
		if (isNumber(ch) || ch == ',' || ch == '.')
			numberPart += ch;
		else if ('NSEWnsewOo'.indexOf(ch) != -1)
			orientationPart += ch;
		else if ('° '.indexOf(ch) != -1)
			; //do nothing
		else
			return undefined;
	}
	
	var number = numberPart * Math.PI / 180;
	if (number < 0.0)
		return undefined;
	
	var orientation = orientationPart.toUpperCase();
	
	if (orientation == 'N' && angle < EPSILON)
		angle = Math.PI / 2;
	else if (orientation == 'S' && angle < EPSILON)
		angle = 3 * Math.PI / 2;
	else if (orientation == 'NE')
		angle = Math.PI / 2 - number;
	else if (orientation == 'NW' || orientation == 'NO')
		angle = Math.PI / 2 + number;
	else if (orientation == 'SW' || orientation == 'SO')
		angle = 3 * Math.PI / 2 - number;
	else if (orientation == 'SE')
		angle = 3 * Math.PI / 2 + number;
	else
		return undefined;
	
	return angle;
}

function isNumber(n) {
	return !isNaN(parseFloat(n)) && isFinite(n);
}

